#include "ui.h"

#include <Arduino.h>
#include <TFT_eSPI.h>

///////////////////// VARIABLES ////////////////////

// SCREEN: ui_Screen1
void ui_Screen1_screen_init(void);
lv_obj_t * ui_Screen1;
lv_obj_t * ui_Container1;
lv_obj_t * ui_Panel5;
lv_obj_t * ui_Panel1;
void ui_event_Button2(lv_event_t * e);
lv_obj_t * ui_Button2;
lv_obj_t * ui_Image5;
lv_obj_t * ui_Panel2;
void ui_event_Button1(lv_event_t * e);
lv_obj_t * ui_Button1;
lv_obj_t * ui_Image6;
lv_obj_t * ui_Panel3;
void ui_event_Switch1(lv_event_t * e);
lv_obj_t * ui_Switch1;
lv_obj_t * ui_Image7;
lv_obj_t * ui_Image9;
lv_obj_t * ui_Home;
lv_obj_t * ui_Arc2;
lv_obj_t * ui_Panel11;
lv_obj_t * ui_Panel12;
lv_obj_t * ui_tembar;
lv_obj_t * ui_humbar;
lv_obj_t * ui_temnum;
lv_obj_t * ui_humnum;
lv_obj_t * ui_templabel;
lv_obj_t * ui_humlabel;
lv_obj_t * ui_Image1;
lv_obj_t * ui_Image4;
lv_obj_t * ui_type;
lv_obj_t * ui_ppm;
lv_obj_t * ui_concentration;
lv_obj_t * ui_Chart;
lv_obj_t * ui_Panel18;
lv_obj_t * ui_Chart1;
lv_obj_t * ui_Label12;
lv_obj_t * ui_Label13;
lv_obj_t * ui_Label14;
lv_obj_t * ui_Label15;
lv_obj_t * ui_Label16;
lv_obj_t * ui_Dropdown1;
lv_obj_t * ui____initial_actions0;

float Voltage[8];
float humidity;
float temperature;

std::string label;
float regression_output;

volatile uint32_t key_pressed = 0;  

lv_indev_t * indev_keypad;

/*Change screen resolution*/
static const uint16_t screenWidth  = 480;
static const uint16_t screenHeight = 320;

static lv_disp_draw_buf_t draw_buf;
static lv_color_t buf1[ screenWidth * screenHeight / 8 ];  
static lv_color_t buf2[ screenWidth * screenHeight / 8 ];  

TFT_eSPI tft = TFT_eSPI(screenWidth, screenHeight); /* TFT instance */

///////////////////// TEST LVGL SETTINGS ////////////////////
#if LV_COLOR_DEPTH != 16
    #error "LV_COLOR_DEPTH should be 16bit to match SquareLine Studio's settings"
#endif
#if LV_COLOR_16_SWAP !=0
    #error "LV_COLOR_16_SWAP should be 0 to match SquareLine Studio's settings"
#endif

///////////////////// ANIMATIONS ////////////////////

///////////////////// FUNCTIONS ////////////////////
void ui_event_Button2(lv_event_t * e)
{
    lv_event_code_t event_code = lv_event_get_code(e);
    lv_obj_t * target = lv_event_get_target(e);
    if(event_code == LV_EVENT_VALUE_CHANGED &&  lv_obj_has_state(target, LV_STATE_CHECKED)) {
        _ui_flag_modify(ui_Home, LV_OBJ_FLAG_HIDDEN, _UI_MODIFY_FLAG_REMOVE);
        _ui_flag_modify(ui_Chart, LV_OBJ_FLAG_HIDDEN, _UI_MODIFY_FLAG_ADD);
        _ui_state_modify(ui_Button1, LV_STATE_CHECKED, _UI_MODIFY_STATE_REMOVE);
    }
}
void ui_event_Button1(lv_event_t * e)
{
    lv_event_code_t event_code = lv_event_get_code(e);
    lv_obj_t * target = lv_event_get_target(e);
    if(event_code == LV_EVENT_VALUE_CHANGED &&  lv_obj_has_state(target, LV_STATE_CHECKED)) {
        _ui_state_modify(ui_Button2, LV_STATE_CHECKED, _UI_MODIFY_STATE_REMOVE);
        _ui_flag_modify(ui_Chart, LV_OBJ_FLAG_HIDDEN, _UI_MODIFY_FLAG_REMOVE);
        _ui_flag_modify(ui_Home, LV_OBJ_FLAG_HIDDEN, _UI_MODIFY_FLAG_ADD);
    }
}
void ui_event_Switch1(lv_event_t * e)
{
    lv_event_code_t event_code = lv_event_get_code(e);
    lv_obj_t * target = lv_event_get_target(e);
    if(event_code == LV_EVENT_VALUE_CHANGED) {
        _ui_flag_modify(ui_Image7, LV_OBJ_FLAG_HIDDEN, _UI_MODIFY_FLAG_TOGGLE);
        _ui_flag_modify(ui_Image9, LV_OBJ_FLAG_HIDDEN, _UI_MODIFY_FLAG_TOGGLE);
    }
    if (lv_obj_has_state(target, LV_STATE_CHECKED)) {
    pinMode(PUMP_SW_PIN, OUTPUT);
    digitalWrite(PUMP_SW_PIN, HIGH);
    } 
    else {
    pinMode(PUMP_SW_PIN, OUTPUT);
    digitalWrite(PUMP_SW_PIN, LOW);
    }
}

void IRAM_ATTR button4_isr() { key_pressed = 1; }
void IRAM_ATTR button5_isr() { key_pressed = 2; }
void IRAM_ATTR button1_isr() { key_pressed = 3; }
void IRAM_ATTR button2_isr() { key_pressed = 4; }
void IRAM_ATTR button6_isr() { key_pressed = 5; }
void IRAM_ATTR button3_isr() { key_pressed = 6; }

static void keypad_init(void)
{
    pinMode(button4, INPUT_PULLUP); //left
    pinMode(button5, INPUT_PULLUP); //up
    pinMode(button1, INPUT_PULLUP); //right
    pinMode(button2, INPUT_PULLUP); //down
    pinMode(button6, INPUT_PULLUP); //back
    pinMode(button3, INPUT_PULLUP); //go

    attachInterrupt(digitalPinToInterrupt(button4), button4_isr, FALLING);
    attachInterrupt(digitalPinToInterrupt(button5), button5_isr, FALLING);
    attachInterrupt(digitalPinToInterrupt(button1), button1_isr, FALLING);
    attachInterrupt(digitalPinToInterrupt(button2), button2_isr, FALLING);
    attachInterrupt(digitalPinToInterrupt(button6), button6_isr, FALLING);
    attachInterrupt(digitalPinToInterrupt(button3), button3_isr, FALLING);
}

static uint32_t keypad_get_key(void)
{
    uint32_t key = key_pressed;
    key_pressed = 0;
    return key;        
}

static void keypad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{
    static uint32_t last_key = 0;

    /*Get whether the a key is pressed and save the pressed key*/
    uint32_t act_key = keypad_get_key();
    if(act_key != 0) {
        data->state = LV_INDEV_STATE_PR;

        /*Translate the keys to LVGL control characters according to key definitions*/
        switch(act_key) {
            case 1:
                act_key = LV_KEY_LEFT;    // LV_KEY_RIGHT
                break;
            case 2:
                act_key = LV_KEY_NEXT;    // LV_KEY_NEXT
                break;
            case 3:
                act_key = LV_KEY_RIGHT;   // LV_KEY_LEFT
                break;
            case 4:
                act_key = LV_KEY_PREV;    // LV_KEY_PREV
                break;
            case 5:
                act_key = LV_KEY_HOME;
                break;
            case 6:
                act_key = LV_KEY_ENTER;
                break;
        }

        last_key = act_key;
    }
    else {
        data->state = LV_INDEV_STATE_REL;
    }
    data->key = last_key;
}

void update_chart(void) {
    char buf[64];
    lv_dropdown_get_selected_str(ui_Dropdown1, buf, sizeof(buf));
    int voltage_index = -1;

    if (strcmp(buf, "Combustible sensor") == 0) {
        voltage_index = 0;
    } else if (strcmp(buf, "H2 sensor") == 0) {
        voltage_index = 1;
    } else if (strcmp(buf, "Smoke sensor") == 0) {
        voltage_index = 2;
    } else if (strcmp(buf, "H2S sensor") == 0) {
        voltage_index = 3;
    } else if (strcmp(buf, "NH3 sensor") == 0) {
        voltage_index = 4;
    } else if (strcmp(buf, "NO2 sensor") == 0) {
        voltage_index = 5;
    } else if (strcmp(buf, "VOC sensor") == 0) {
        voltage_index = 6;
    } else if (strcmp(buf, "CO sensor") == 0) {
        voltage_index = 7;
    }

    if (voltage_index != -1) {
        for (int i = 0; i < 14; i++) {
            ui_Chart1_series_1_array[i] = ui_Chart1_series_1_array[i + 1]; 
        }
        ui_Chart1_series_1_array[14] = (lv_coord_t)(Voltage[voltage_index] * 1000);

        // lv_coord_t max_value = ui_Chart1_series_1_array[0];

        // for (int i = 0; i < 14; i++) {
        //   if (ui_Chart1_series_1_array[i] > max_value) {
        //       max_value = ui_Chart1_series_1_array[i];
        //   }
        // }
        // // 更新 Y 轴范围
        // lv_chart_set_range(ui_Chart1, LV_CHART_AXIS_PRIMARY_Y, 0, max_value);

        lv_chart_set_ext_y_array(ui_Chart1, ui_Chart1_series_1, ui_Chart1_series_1_array);
        lv_chart_refresh(ui_Chart1);
    }

    int arc_value = (int)regression_output;

    if (arc_value < 0) arc_value = 0;
    if (arc_value > 1000) arc_value = 1000;

    char temp_str[10];
    snprintf(temp_str, sizeof(temp_str), "%.2f", temperature);
    lv_label_set_text(ui_temnum, temp_str);
    snprintf(temp_str, sizeof(temp_str), "%.2f", humidity);
    lv_label_set_text(ui_humnum, temp_str);

    lv_arc_set_value(ui_Arc2, regression_output);

    snprintf(temp_str, sizeof(temp_str), "%d", arc_value);
    lv_label_set_text(ui_concentration, temp_str);

    lv_label_set_text(ui_type, label.c_str());
}

/* Display flushing */
void my_disp_flush( lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p )
{
    uint32_t w = ( area->x2 - area->x1 + 1 );
    uint32_t h = ( area->y2 - area->y1 + 1 );

    tft.startWrite();
    tft.setAddrWindow( area->x1, area->y1, w, h );
    tft.pushColors( ( uint16_t * )&color_p->full, w * h, true );
    tft.endWrite();

    lv_disp_flush_ready( disp_drv );
}

///////////////////// SCREENS ////////////////////
void user_init(void)
{
    
  tft.begin();
  tft.setRotation( 1 ); 

  lv_disp_draw_buf_init( &draw_buf, buf1, buf2, screenWidth * screenHeight / 8);

  /*Initialize the display*/
  static lv_disp_drv_t disp_drv;
  lv_disp_drv_init( &disp_drv );
  /*Change the following line to display resolution*/
  disp_drv.hor_res = screenWidth;
  disp_drv.ver_res = screenHeight;
  disp_drv.flush_cb = my_disp_flush;
  disp_drv.draw_buf = &draw_buf;
  lv_disp_drv_register( &disp_drv );
  ui_init();
  /*Initialize the (dummy) input device driver*/
  static lv_indev_drv_t indev_drv;
  keypad_init();
  lv_indev_drv_init(&indev_drv);
  indev_drv.type = LV_INDEV_TYPE_KEYPAD;
  indev_drv.read_cb = keypad_read;
  indev_keypad = lv_indev_drv_register(&indev_drv);
  
  lv_group_t *group = lv_group_create();
  lv_indev_set_group(indev_keypad, group);
  lv_group_add_obj(group ,ui_Button1);
  lv_group_add_obj(group ,ui_Button2);
  lv_group_add_obj(group ,ui_Dropdown1);
  lv_group_add_obj(group ,ui_Switch1);
}

void ui_init(void)
{
    lv_disp_t * dispp = lv_disp_get_default();
    lv_theme_t * theme = lv_theme_default_init(dispp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED),
                                               false, LV_FONT_DEFAULT);
    lv_disp_set_theme(dispp, theme);
    ui_Screen1_screen_init();
    ui____initial_actions0 = lv_obj_create(NULL);
    lv_disp_load_scr(ui_Screen1);
}
